#include "rotor.h"
#include "enigma.h"

#include <QDebug>

//"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
//"EKMFLGDQVZNTOWYHXUSPAIBRCJ"
//"AJDKSIRUXBLHWTMCQGZNPYFVOE"
//"BDFHJLCPRTXVZNYEIWGAKMUSQO"
//"ESOVPZJAYQUIRHXLNFTGKDCMWB"
//"VZBRGITYUPSDNHLXAWMJQOFECK"
//"JPGVOUMFYQBENHZRDKASXLICTW"
//"NZJHGRCXMYSWBOUFAIVLPEKQDT"
//"FKQHTLXOCBJSPDZRAMEWNIUYGV"
/*
 * Rotor
 */
Rotor::Rotor() :
    m_next(nullptr),
    m_cursor(0)
{
    m_letters.resize(ROTOR_LETTERS_NUMB);
    m_reversedLetters.resize(ROTOR_LETTERS_NUMB);

    setRotorLetters(QByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
}

void Rotor::setRotorPhase(char ch)
{
    m_cursor = ch - 'A';
}

void Rotor::setRotorNotch(char ch)
{
    m_notchs.append(ch - 'A');
}

void Rotor::setRotorLetters(const QByteArray &letters)
{
    if (letters.length() != ROTOR_LETTERS_NUMB) return;

    for (int i = 0; i < ROTOR_LETTERS_NUMB; i++) {
        m_letters[i] = letters[i];
    }
    for (int i = 0; i < ROTOR_LETTERS_NUMB; i++) {
        m_reversedLetters[m_letters[i] - 'A'] = i + 'A';
    }
}

void Rotor::setRotorNext(Rotor *next)
{
    m_next = next;
}

void Rotor::rotate()
{
    m_cursor = (m_cursor + 1) % ROTOR_LETTERS_NUMB;
    if ((m_next != nullptr) && (m_notchs.contains(m_cursor))) {
        m_next->rotate();
    }
//    char ch1 = 'A';
//    for (int i = 0; i < ROTOR_LETTERS_NUMB; i++) {
//        qDebug() << ch1 << getRotorChar(ch1);
//        ch1++;
//    }
}

char Rotor::getRotorChar(char ch)
{
    char letter = m_letters[((ch - 'A') + m_cursor) % ROTOR_LETTERS_NUMB];
    letter = ((letter - 'A') + ROTOR_LETTERS_NUMB - m_cursor) % ROTOR_LETTERS_NUMB + 'A';
    return letter;
}

char Rotor::getRotorCharReversed(char ch)
{
    char letter = m_reversedLetters[((ch - 'A') + m_cursor) % ROTOR_LETTERS_NUMB];
    letter = ((letter - 'A') + ROTOR_LETTERS_NUMB - m_cursor) % ROTOR_LETTERS_NUMB + 'A';
    return letter;
}

/*
 * Plugboard
 */
Plugboard::Plugboard()
{

}

void Plugboard::setPlugboardPairs(const QMap<char, char> &pairs)
{
    QByteArray letters("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

    QMap<char, char>::const_iterator itor;
    for (itor = pairs.begin(); itor != pairs.end(); itor++) {
        letters[itor.key() - 'A'] = itor.value();
        letters[itor.value() - 'A'] = itor.key();
    }
    setRotorLetters(letters);
}

/*
 * Reflector
 */
Reflector::Reflector()
{

}

void Reflector::setReflectorPairs(const QMap<char, char> &pairs)
{
    setPlugboardPairs(pairs);
}

/*
 * RotorI
 */
RotorI::RotorI()
{
    setRotorLetters(QByteArray("EKMFLGDQVZNTOWYHXUSPAIBRCJ"));
    setRotorNotch('R');
}

/*
 * RotorII
 */
RotorII::RotorII()
{
    setRotorLetters(QByteArray("AJDKSIRUXBLHWTMCQGZNPYFVOE"));
    setRotorNotch('F');
}

/*
 * RotorIII
 */
RotorIII::RotorIII()
{
    setRotorLetters(QByteArray("BDFHJLCPRTXVZNYEIWGAKMUSQO"));
    setRotorNotch('W');
}

/*
 * RotorIV
 */
RotorIV::RotorIV()
{
    setRotorLetters(QByteArray("ESOVPZJAYQUIRHXLNFTGKDCMWB"));
    setRotorNotch('K');
}

/*
 * RotorV
 */
RotorV::RotorV()
{
    setRotorLetters(QByteArray("VZBRGITYUPSDNHLXAWMJQOFECK"));
    setRotorNotch('A');
}

/*
 * RotorVI
 */
RotorVI::RotorVI()
{
    setRotorLetters(QByteArray("JPGVOUMFYQBENHZRDKASXLICTW"));
    setRotorNotch('A');
    setRotorNotch('N');
}

/*
 * RotorVII
 */
RotorVII::RotorVII()
{
    setRotorLetters(QByteArray("NZJHGRCXMYSWBOUFAIVLPEKQDT"));
    setRotorNotch('A');
    setRotorNotch('N');
}

/*
 * RotorVIII
 */
RotorVIII::RotorVIII()
{
    setRotorLetters(QByteArray("FKQHTLXOCBJSPDZRAMEWNIUYGV"));
    setRotorNotch('A');
    setRotorNotch('N');
}

ReflectorB::ReflectorB()
{
    QMap<char,char> pairs;
    pairs.insert('A', 'Y');
    pairs.insert('B', 'R');
    pairs.insert('C', 'U');
    pairs.insert('D', 'H');
    pairs.insert('E', 'Q');
    pairs.insert('F', 'S');
    pairs.insert('G', 'L');
    pairs.insert('I', 'P');
    pairs.insert('J', 'X');
    pairs.insert('K', 'N');
    pairs.insert('M', 'O');
    pairs.insert('T', 'Z');
    pairs.insert('V', 'W');
    setReflectorPairs(pairs);
}

ReflectorC::ReflectorC()
{
    QMap<char,char> pairs;
    pairs.insert('A', 'F');
    pairs.insert('B', 'V');
    pairs.insert('C', 'P');
    pairs.insert('D', 'J');
    pairs.insert('E', 'I');
    pairs.insert('G', 'O');
    pairs.insert('H', 'Y');
    pairs.insert('K', 'R');
    pairs.insert('L', 'Z');
    pairs.insert('M', 'X');
    pairs.insert('N', 'W');
    pairs.insert('S', 'U');
    pairs.insert('T', 'Q');
    setReflectorPairs(pairs);
}
